package myLogger

import (
	"fmt"
	"os"
	"path"
	"time"
)

//往文件里写日志相关代码

type FileLogger struct{
	Level LogLevel
	FilePath string //文件保存的路径
	FileName string // 文件保存的名字
	fileObj *os.File
	errFileObj *os.File
	maxFileSize int64 // 最大文件大小
}

//NewFileLogger 日志结构体构造函数
func NewFileLogger(levelStr, fp, fn string, maxSize int64)*FileLogger{
	logLevel, err := parseLogLevel(levelStr)
	if err != nil{
		panic(err)
	}
	fl := &FileLogger{
		Level: logLevel,
		FilePath: fp,
		FileName: fn,
		maxFileSize: maxSize,
	}
	fl.initFile() //按照文件路径和文件名将文件打开
	return fl
}

func (f *FileLogger)initFile()(error){
	fullFileName := path.Join(f.FilePath, f.FileName)
	fileObj, err := os.OpenFile(fullFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY,0644)
	if err != nil{
		fmt.Printf("Open log file filed, err:%v\n", err)
		return err
	}
	errFileObj, err := os.OpenFile(fullFileName + ".err", os.O_APPEND|os.O_CREATE|os.O_WRONLY,0644)
	if err != nil{
		fmt.Printf("Open err log file filed, err:%v\n", err)
		return err
	}
	//日志文件打开后
	f.fileObj = fileObj
	f.errFileObj = errFileObj
	return nil
}

func (f *FileLogger) Close(){
	f.fileObj.Close()
	f.errFileObj.Close()
}

func (f *FileLogger)enable(logLevel LogLevel)bool{
	return logLevel >= f.Level
}

func (f *FileLogger) Debug(format string, a...interface{}){
	f.log(DEBUG, format, a...)
}

func (f *FileLogger) Trace(format string, a...interface{}){
	f.log(TRACE, format, a...)
}

func (f *FileLogger) Info(format string, a...interface{}){
	f.log(INFO, format, a...)
}

func (f *FileLogger) Warning(format string, a...interface{}){
	f.log(WARNING, format, a...)
}

func (f *FileLogger) Error(format string, a...interface{}){
	f.log(ERROR, format, a...)
}

func (f *FileLogger) Fatal (format string, a...interface{}){
	f.log(FATAL, format, a...)
}

func (f *FileLogger)log(lv LogLevel, format string, a...interface{}){
	if f.enable(lv) {
		msg := fmt.Sprintf(format, a...)
		now := time.Now()
		funcName, fileName, lineNo := getInfo(3)
		if f.checkSize(f.fileObj){
			//需要切割
			newFile, err := f.splitFile(f.fileObj)
			if err != nil{
				return
			}
			f.fileObj = newFile
		}
		fmt.Fprintf(f.fileObj,"[%s] [%s] [%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), fileName, funcName, lineNo, msg)
		if lv >= ERROR{
			// 日志级别大于ERROR
			if f.checkSize(f.errFileObj){
				//需要切割
				newFile, err := f.splitFile(f.errFileObj)
				if err != nil{
					return
				}
				f.errFileObj = newFile
			}
			fmt.Fprintf(f.errFileObj,"[%s] [%s] [%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), fileName, funcName, lineNo, msg)
		}
	}
}

func(f *FileLogger)checkSize(file *os.File)bool{
	fileInfo, err := file.Stat()
	if err != nil{
		fmt.Printf("get file info failed,err:%v\n", err)
		return false
	}
	//当前文件大小大于等于最大值
	return fileInfo.Size() >= f.maxFileSize
}

func (f *FileLogger) splitFile(file *os.File) (*os.File, error) {
	nowStr := time.Now().Format("20060102150405000")
	fileInfo, err := file.Stat()
	if err != nil{
		fmt.Printf("Get file info filed, err:%v\n", err)
		return nil, err
	}
	logName := path.Join(f.FilePath, fileInfo.Name())
	newLogName := fmt.Sprintf("%s.bak%s", logName, nowStr)
	//1。关闭当前文件
	file.Close()
	//2。备份rename
	os.Rename(logName, newLogName)
	//3。打开新的日志文件
	fileObj, err := os.OpenFile(logName, os.O_CREATE|os.O_APPEND|os.O_WRONLY,0644)
	if err != nil{
		fmt.Printf("Open new log file filed, err:%v\n", err)
		return nil, err
	}
	//4。将新文件赋值给f.obj
	return fileObj, nil
}